﻿namespace TNet
{
    using System;
    using System.IO;
    using System.Net;
    using System.Threading;

    public class TcpLobbyServerLink : LobbyServerLink
    {
        private long mNextConnect;
        private IPEndPoint mRemoteAddress;
        private TcpProtocol mTcp;
        private long mTimeDifference;
        private bool mWasConnected;

        public TcpLobbyServerLink(IPEndPoint address) : base(null)
        {
            this.mRemoteAddress = address;
        }

        public override void SendUpdate(GameServer server)
        {
            if (!base.mShutdown)
            {
                base.mGameServer = server;
                if (base.mThread == null)
                {
                    base.mThread = new Thread(new ThreadStart(this.ThreadFunction));
                    base.mThread.Start();
                }
            }
        }

        public override void Start()
        {
            base.Start();
            if (this.mTcp == null)
            {
                this.mTcp = new TcpProtocol();
                this.mTcp.name = "Link";
            }
            this.mNextConnect = 0L;
        }

        private void ThreadFunction()
        {
            long num;
            base.mInternal = new IPEndPoint(Tools.localAddress, base.mGameServer.tcpPort);
            base.mExternal = new IPEndPoint(Tools.externalAddress, base.mGameServer.tcpPort);
        Label_003B:
            num = DateTime.UtcNow.Ticks / 0x2710L;
            if (base.mShutdown)
            {
                this.mTcp.Disconnect();
                base.mThread = null;
            }
            else
            {
                TNet.Buffer buffer;
                if (((base.mGameServer != null) && !this.mTcp.isConnected) && (this.mNextConnect < num))
                {
                    this.mNextConnect = num + 0x3a98L;
                    this.mTcp.Connect(this.mRemoteAddress);
                }
                while (this.mTcp.ReceivePacket(out buffer))
                {
                    BinaryReader reader = buffer.BeginReading();
                    Packet packet = (Packet) reader.ReadByte();
                    if (this.mTcp.stage == TcpProtocol.Stage.Verifying)
                    {
                        if (!this.mTcp.VerifyResponseID(packet, reader))
                        {
                            base.mThread = null;
                            return;
                        }
                        this.mTimeDifference = reader.ReadInt64() - (DateTime.UtcNow.Ticks / 0x2710L);
                        this.mWasConnected = true;
                    }
                    else if (packet == Packet.Error)
                    {
                        this.mNextConnect = !this.mWasConnected ? (num + 0x7530L) : 0L;
                    }
                    buffer.Recycle();
                }
                if ((base.mGameServer != null) && this.mTcp.isConnected)
                {
                    BinaryWriter writer = this.mTcp.BeginSend(Packet.RequestAddServer);
                    writer.Write((ushort) 1);
                    writer.Write(base.mGameServer.name);
                    writer.Write((short) base.mGameServer.playerCount);
                    Tools.Serialize(writer, base.mInternal);
                    Tools.Serialize(writer, base.mExternal);
                    this.mTcp.EndSend();
                    base.mGameServer = null;
                }
                Thread.Sleep(10);
                goto Label_003B;
            }
        }

        public override bool isActive
        {
            get
            {
                return this.mTcp.isConnected;
            }
        }

        public long serverTime
        {
            get
            {
                return (this.mTimeDifference + (DateTime.UtcNow.Ticks / 0x2710L));
            }
        }
    }
}

